package cn.alusiaor.eurekaclientarticleservice.config;

import cn.alusiaor.eurekaclientarticleservice.constant.ResponseCodeStatus;
import cn.alusiaor.eurekaclientarticleservice.exception.CustomException;
import cn.alusiaor.eurekaclientarticleservice.response.CommonResult;
import cn.hutool.json.JSONUtil;
import feign.FeignException;
import feign.Response;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import feign.optionals.OptionalDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * @author zhuzhiping
 * @description
 * @date 2021/1/19 10:56
 */
@Configuration
public class MultipartSupportConfig {
    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    public Encoder feignFormEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }

    @Bean
    public Decoder decoder() {
        return new FeignDecoder(
                new OptionalDecoder(
                        new ResponseEntityDecoder(
                                new SpringDecoder(messageConverters))));
    }

    @Slf4j
    public static class FeignDecoder implements Decoder {
        // 代理默认的解码器
        private final Decoder decoder;

        public FeignDecoder(Decoder decoder) {
            this.decoder = decoder;
        }

        @Override
        public Object decode(Response response, Type type) throws IOException, FeignException {
            // 序列化为json
            String json = this.getResponseJson(response);
            this.processCommonException(json);
            return decoder.decode(response, type);
        }

        // 处理公共业务异常
        private void processCommonException(String json) {
            if (!StringUtils.hasLength(json)) {
                return;
            }
            CommonResult resp = JSONUtil.toBean(json, CommonResult.class);
            if (Objects.equals(resp.getCode(), ResponseCodeStatus.success)) {
                return;
            }
            log.info("feign response error: code={}, message={},error={}", resp.getCode(), resp.getMsg(),resp.getError());
            // 抛出我们期望的业务异常
            throw new CustomException(resp.getCode(), resp.getMsg());
        }

        // 响应值转json字符串
        private String getResponseJson(Response response) throws IOException {
            try (InputStream inputStream = response.body().asInputStream()) {
                return StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
            }
        }
    }

}
